#include "table.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QFile>
#include <QFileInfo>
#include <QDebug>

Table::Table() {}

Table::~Table()
{
    clearAll();
}

QList<DataItem *> &Table::data()
{
    return m_datas;
}

void Table::setData(const QList<DataItem *> &newData)
{
    m_datas = newData;
}

void Table::addDataItem(DataItem *item)
{
    m_datas.push_back(item);
}

void Table::addDataItem(const QString &_sn, const QString &_name, bool _hotspot, int _usb, const QString &_note)
{
    DataItem *item = new DataItem(_sn, _name, _hotspot, _usb, _note);
    addDataItem(item);
}

void Table::clearAll()
{
    foreach (DataItem *item, m_datas) {
        if(item)
            delete item;
    }
    m_datas.clear();
}

bool Table::load(const QString &fileName, SaveFormat format, bool clearOldData)
{
    if(clearOldData)
        clearAll();
    if(format == JsonFormat)
        return loadFromJson(fileName, m_datas);
    else if(format == DBFormat)
        return loadFromDatabase(fileName, m_datas);
    else
        return false;
}

bool Table::save(const QString &fileName, SaveFormat format)
{
    if(format == JsonFormat)
        return saveToJson(fileName, m_datas);
    else if(format == DBFormat)
        return saveToDatabase(fileName, m_datas);
    else
        return false;
}

/*
{
    "name": "table_1",
    "datas": [
        {
            "sn": "123456",
            "name": "sweepea",
            "hotspot": true,
            "usb": 310,
            "note": ""
        }
    ]
}
*/

bool Table::loadFromJson(const QString &fileName, QList<DataItem *> &datas)
{
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly)) {
        qDebug() << "open file fail. " << fileName << "reason: " << file.errorString();
        return false;
    }
    auto ba = file.readAll();
    QJsonParseError err;
    auto doc = QJsonDocument::fromJson(ba, &err);
    if(err.error != QJsonParseError::NoError) {
        qDebug() << "load json fail. " << fileName << "reason: " << err.errorString();
        return false;
    }
    QJsonObject root = doc.object();
    if(root.contains("datas") && root["datas"].isArray()) {
        QJsonArray ja = root["datas"].toArray();
        for(int i = 0; i < ja.size(); i++) {
            const auto &itemV = ja.at(i);
            if(itemV.isObject()) {
                const auto &item = itemV.toObject();
                if(item.contains("sn") && item.contains("name")) {
                    DataItem *d = new DataItem(item["sn"].toString(),
                                               item["name"].toString(),
                                               item.contains("hotspot") ? item["hotspot"].toBool() : false,
                                               item.contains("usb") ? item["usb"].toInt() : 0,
                                               item.contains("note") ? item["note"].toString() : QString()
                                               );
                    m_datas.push_back(d);
                }
            }
        }
    }
    qDebug() << "Table datas: " << m_datas.size() << root;
    return true;
}

bool Table::loadFromDatabase(const QString &fileName, QList<DataItem *> &datas)
{
    return false;
}

bool Table::saveToJson(const QString &fileName, const QList<DataItem *> &datas)
{
    QFile file(fileName);
    if(!file.open(QIODevice::WriteOnly)) {
        qDebug() << "open file fail. " << fileName << "reason: " << file.errorString();
        return false;
    }
    QJsonObject root;
    root["name"] = QFileInfo(fileName).fileName();
    QJsonArray ja;
    foreach (DataItem *item, m_datas) {
        if(item) {
            QJsonObject o;
            o["sn"] = item->sn;
            o["name"] = item->name;
            o["hotspot"] = item->hotspot;
            o["usb"] = item->usb;
            o["note"] = item->note;
            ja.push_back(o);
        }
    }
    root["datas"] = ja;
    QJsonDocument doc(root);
    file.write(doc.toJson());
    file.close();
    return true;
}

bool Table::saveToDatabase(const QString &fileName, const QList<DataItem *> &datas)
{
    return false;
}
